
#include <string.h>

#include <db.h>
#include <assert.h>
#include <stdlib.h>

#include "lang/morestdio.h"
#include "lang/morestdlib.h"
#include "lang/morestring.h"
#include "util/debug.h"
#include "util/error.h"
#include "core/operon.h"



 static int _openDB(struct Operon_t* operon,struct OperonDB_t* ptr)
	 {
	 operon->count_open_databases++;
	 }

 static int _closeDB(struct Operon_t* operon,struct OperonDB_t* ptr)
	 {
	 operon->count_open_databases--;
	 }


#define TEST_ERROR(method) {if((error_no=(method))!=0)\
        {\
        DEBUG3("Could not do %s errno=%s",#method,db_strerror(error_no));\
        failure=1;\
        goto cleanup;\
        }} while(0)


/**
 * creates a new Operon
 * @return a new pointer on operon
 */
OperonPtr OperonNew()
	{
	int failure=0;
	OperonPtr operon= (OperonPtr)Calloc(1,sizeof(Operon));
	if(operon==NULL)
		{
		DEBUG;
		return NULL;
		}
	//initialize ptr
	operon->openDB=_openDB;
	operon->closeDB=_closeDB;


#ifdef TEST_THIS_CODE
    TEST_ERROR((db_env_create(&(operon->dbenv),config->create_flags)));
    operon->dbenv->set_errfile(operon->dbenv,config->error_stream);
    if(config->gbytes>0 ||
       config->bytes>0 ||
       config->ncache>0)
        {
        TEST_ERROR((operon->dbenv->set_cachesize(
                operon->dbenv,
                config->gbytes,
                config->bytes,
                config->ncache
                )));
        }
    if(config->error_prefix!=NULL)
        operon->dbenv->set_errpfx(operon->dbenv,config->error_prefix);
    if(config->logDir!=NULL)
        TEST_ERROR((operon->dbenv->set_lg_dir(operon->dbenv,config->logDir)));
    if(config->tmpDir!=NULL)
        TEST_ERROR((operon->dbenv->set_tmp_dir(operon->dbenv,config->tmpDir)));
    if(config->dataDir!=NULL)
        TEST_ERROR((operon->dbenv->set_data_dir(operon->dbenv,config->dataDir)));


    TEST_ERROR((operon->dbenv->open(
                    (operon->dbenv),
                    config->homeDir,
                    config->open_flags,
                    0//config->open_mode
                    )));
	#endif

     cleanup:
         if(failure)
            {
            DEBUG;
            OperonDelete(operon);
            operon=NULL;
            }
     DEBUG;
     return operon;

	}

void OperonDelete(OperonPtr ptr)
	{
	if(ptr==NULL) return;
	if(ptr->dbenv!=NULL)
		{
		int ret=ptr->dbenv->close(ptr->dbenv,0);
		if(ret!=0)
			{
			DEBUG2("Close env failed %s",db_strerror(ret));
			}
		}
	Free(ptr);
	}


#ifdef TEST_THIS_CODE



OperonPtr operon_fromConfig(const DBEnvInitParamsPtr config)
    {
    int failure=0;
    int error_no=0;
    if(config==NULL) return NULL;
    OperonPtr operon=NULL;
     DEBUG;

     /*if(config->dataDir==NULL)
        {
        DEBUG1("No data dir defined");
        failure=1;
        goto cleanup;
        }*/

     DEBUG;
    operon=(OperonPtr)Calloc(1,sizeof(Operon));
        if(operon==NULL)
            {
            failure=1;
            goto cleanup;
            }

    TEST_ERROR((db_env_create(&(operon->dbenv),config->create_flags)));
    //TEST_ERROR((operon->dbenv->set_flags((operon->dbenv),config->set_flags,1)));
    //TEST_ERROR((operon->dbenv->set_flags((operon->dbenv),config->unset_flags,0)));
    operon->dbenv->set_errfile(operon->dbenv,config->error_stream);
     DEBUG;
    if(config->gbytes>0 ||
       config->bytes>0 ||
       config->ncache>0)
        {
        TEST_ERROR((operon->dbenv->set_cachesize(
                operon->dbenv,
                config->gbytes,
                config->bytes,
                config->ncache
                )));
        }
    if(config->error_prefix!=NULL)
        operon->dbenv->set_errpfx(operon->dbenv,config->error_prefix);
    if(config->logDir!=NULL)
        TEST_ERROR((operon->dbenv->set_lg_dir(operon->dbenv,config->logDir)));
    if(config->tmpDir!=NULL)
        TEST_ERROR((operon->dbenv->set_tmp_dir(operon->dbenv,config->tmpDir)));
    if(config->dataDir!=NULL)
        TEST_ERROR((operon->dbenv->set_data_dir(operon->dbenv,config->dataDir)));


    TEST_ERROR((operon->dbenv->open(
                    (operon->dbenv),
                    config->homeDir,
                    config->open_flags,
                    0//config->open_mode
                    )));

     cleanup:
         if(failure)
            {
             DEBUG;
            operon_delete(operon);
            operon=NULL;
            }
     DEBUG;
     return operon;
     }






int main(int argc,char ** argv)
    {
    DEBUG;
    DBEnvInitParams param;
    memset(&param,sizeof(DBEnvInitParams),0);
    const char* home_dir="/tmp/operon0";
    const char* datadir="data";
    param.create_flags=(u_int32_t)0;
    param.set_flags=0;
    param.open_flags=   DB_CREATE |    /* Create the environment if it does
                                * not already exist. */
                DB_INIT_TXN  | /* Initialize transactions */
                DB_INIT_LOCK | /* Initialize locking. */
                DB_INIT_LOG  | /* Initialize logging */
                DB_INIT_MPOOL; /* Initialize the in-memory cache. */

    param.open_mode = 0664;
    param.homeDir = home_dir;
    param.dataDir = NULL;//datadir;
     DEBUG;
    OperonPtr ptr=operon_fromConfig(&param);
    if(ptr!=NULL)
        {
        printf("OK");
        }
    DEBUG;
    operon_delete(ptr);
    return 0;
    }
#endif
